﻿using MonitorPrism_Practice.EnumData;
using MonitorPrism_Practice.Model;
using S7.Net;
using SCADALight.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;


namespace MonitorPrism_Practice.Services
{
    public class CommunicationS7 : IPlcService, IDisposable
    {
        public bool IsConnected => S7Plc?.IsConnected == true;
        public readonly Plc S7Plc;
        private bool _disposed = false;
        private LogEventService _logEventService;
        public CommunicationS7(string cpu, string id, short rock, short slot)
        {
            _logEventService = _logEventService = ContainerLocator.Current.Resolve<LogEventService>();
            if (Enum.TryParse(cpu, true, out CpuType_Enum cpuType))
            {
                S7Plc = new Plc((CpuType)Enum.Parse(typeof(CpuType_Enum), cpu), id, rock, slot);
            }

        }
        public void Disconnect()
        {
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
            {
                try
                {
                    Application.Current.Dispatcher.Invoke(() => { S7Plc?.Close(); });
                }
                catch (Exception ex)
                {
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        MessageBox.Show($"断开连接失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    });
                }
            }));
        }
        public void Dispose()
        {
            Dispose();
            GC.SuppressFinalize(this);
        }

        public async Task<bool> OpenAsync(CancellationToken token = default)
        {
            int retryCount = 0;
            const int maxRetries = 10; // 最大重试次数，避免无限循环
            while (!token.IsCancellationRequested)
            {
                if (S7Plc != null && !S7Plc.IsConnected)
                {
                    var connectTask = Task.Run(async () =>
                    {
                        try
                        {
                            S7Plc.Open();
                        }
                        catch (Exception ex)
                        {
                            _logEventService.AddItem(new LogEventModel() { Message = $"通信连接失败:{ex.Message}", Source = "S7通信检测" });

                        }
                    }, token);
                    await connectTask;
                    if (S7Plc.IsConnected)
                    {
                        _logEventService.AddItem(new LogEventModel() { Message = $"通信连接成功:地址：192.168.0.1", Source = "S7通信检测" });
                        return true;
                    }
                }
                retryCount++;
                if (retryCount > maxRetries)
                {
                    MessageBox.Show("达到最大重试次数，连接失败");
                    return false;
                }
                await Task.Delay(1000, token); // 等待1秒
            }
            return false; // 任务被取消
        }
        public void Close()
        {
            Action action = () => { S7Plc.Close(); };
            if (S7Plc != null && S7Plc.IsConnected == true)
            {
                action.Invoke();
                if (S7Plc.IsConnected != true)
                {
                    MessageBox.Show("关闭成功");
                }
            }
        }


        public void ReadData(InterfaceReciveDataModel model)
        {
            try
            {
                if (S7Plc != null && S7Plc.IsConnected != false)
                {
                    switch (model.DataType)
                    {
                        case VarType.Bit:
                            dynamic booer = S7Plc.Read(model.Address);
                            model.Value = Convert.ToString(booer);
                            break;
                        case VarType.Byte:
                            break;
                        case VarType.Word:
                            dynamic word;
                            if (model.Address != null) {word = S7Plc.Read(model.Address); }
                            else {  word = S7Plc.Read(DataType.DataBlock, model.DbIndex, model.DbDataIndex, VarType.Real, 1); }
                            ushort wordValue = Convert.ToUInt16(word);
                            model.Value = wordValue.ToString();
                            break;
                        case VarType.DWord:
                            dynamic dWord;
                            if (model.Address != null) { dWord = S7Plc.Read(model.Address); }
                            else { dWord = S7Plc.Read(DataType.DataBlock, model.DbIndex, model.DbDataIndex, VarType.Real, 1); }
                            UInt32 dWordValue = Convert.ToUInt32(dWord);
                            model.Value = dWordValue.ToString();
                            break;
                        case VarType.Int:
                            dynamic shortValue;
                            if (model.Address != null) { shortValue = S7Plc.Read(model.Address); }
                            else { shortValue = S7Plc.Read(DataType.DataBlock, model.DbIndex, model.DbDataIndex, VarType.Real, 1); }
                            Int16 ShortValue = Convert.ToUInt16(shortValue);
                            model.Value = ShortValue.ToString();
                            break;
                        case VarType.DInt:
                            dynamic intValue;
                            if (model.Address != null) { intValue = S7Plc.Read(model.Address); }
                            else { intValue = S7Plc.Read(DataType.DataBlock, model.DbIndex, model.DbDataIndex, VarType.Real, 1); }
                            Int32 IntValue = Convert.ToUInt32(intValue);
                            model.Value = IntValue.ToString();
                            break;
                        case VarType.Real:
                            dynamic obj = S7Plc.Read(DataType.DataBlock, model.DbIndex, model.DbDataIndex, VarType.Real, 1);
                            float value = Convert.ToSingle(obj);
                            model.Value = value.ToString("0.00");
                            break;
                        case VarType.LReal:
                            break;
                        case VarType.String:
                            break;
                        case VarType.S7String:
                            break;
                        case VarType.S7WString:
                            break;
                        case VarType.Timer:
                            break;
                        case VarType.Counter:
                            break;
                        case VarType.DateTime:
                            break;
                        case VarType.DateTimeLong:
                            break;
                        default:
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                _logEventService.AddItem(new LogEventModel() { Message = $"S7异常{ex.Message}", Source = "S7通信检测" });
            }
        }

        public void WriteData(InterfaceReciveDataModel interfaceReciveDataModel)
        {
            if (S7Plc != null && S7Plc.IsConnected != false)
            {
                switch (interfaceReciveDataModel.DataType)
                {
                    case VarType.Real:

                        S7Plc.Write(DataType.DataBlock, interfaceReciveDataModel.DbIndex, interfaceReciveDataModel.DbDataIndex, Convert.ToSingle(interfaceReciveDataModel.Value));
                        break;
                    case VarType.Bit:

                        S7Plc.Write(DataType.DataBlock, interfaceReciveDataModel.DbIndex, interfaceReciveDataModel.DbDataIndex, Convert.ToBoolean(interfaceReciveDataModel.Value));
                        break;
                    default:
                        break;
                }
            }
        }


    }




}
